<template>
  <qiun-data-charts
    :canvas2d="true"
    :ontouch="true"
    :opts="opts"
    :chartData="chartData"
    type="mix"
    :onzoom="true"
    tooltipFormat="tooltipFormat"
    id="height-echarts"
  />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { getPatientMonthData } from "./index";

const opts = {
  color: [
    "#FBCDCD",
    "#FFE3D3",
    "#B4EBDB",
    "#9BE1DB",
    "#E8F3DB",
    "#ECF5FF",
    "#CBD4FF",
    "#00D1B6",
  ],
  dataPointShapeType: "hollow",
  padding: [25, 18, 0, 0],
  dataLabel: false,
  dataPointShape: true,
  enableScroll: true,
  scrollAlign: "left",
  onShadow: true,
  legend: {
    show: false,
  },
  xAxis: {
    disableGrid: true,
    scrollShow: true,
    itemCount: 6,
    labelCount: 6,
    format: "ageFormat",
    fontColor: "#999",
  },
  yAxis: {
    gridType: "dash",
    dashLength: 4,
    showTitle: true,
    splitNumber: 16,
    gridColor: "#E5E6EB",
    data: [
      {
        title: "单位：cm",
        titleOffsetY: -10,
        titleOffsetX: -60,
        calibration: true,
        fontColor: "#999999",
        max: 200,
      },
    ],
  },
  extra: {
    tooltip: {
      borderRadius: 8,
    },
    mix: {
      line: {
        width: 1,
      },
      area: {
        width: 1,
        type: "curve",
        gradient: false,
        addLine: true,
        opacity: 1,
        activeType: "hollow",
      },
    },
  },
};

interface chartDataType {
  series: Array<any>;
  categories: Array<any>;
}

const chartJson = ref();
const chartData = ref<chartDataType>();
const isReady = ref<boolean>(false);

const props = defineProps({
  patientId: {
    type: Number,
    default: 0,
  },
  userSex: {
    type: Number,
    default: 1,
  },
  type: {
    type: String,
    default: "PValue",
  },
});

const DAYTIMES = 24 * 60 * 60 * 1000;
const DAYSMONTH = 30;

onMounted(async () => {
  await getJsonFileData();
});

watch(
  () => [props.userSex, props.type, props.patientId, isReady.value],
  ([sex, type, patientId, isReady]) => {
    if (
      !patientId ||
      sex == null ||
      sex == undefined ||
      !chartJson.value ||
      !isReady
    ) {
      return;
    }
    setData(patientId, sex, type);
  },
  { immediate: true }
);

const getJsonFileData = () => {
  return new Promise<void>((resolve, reject) => {
    uni.request({
      url: "https://ims.meilianshuke.com/echart_data.json",
      method: "GET",
      success: (res) => {
        chartJson.value = res.data;

        chartData.value = {
          series: [],
          categories: [],
        };

        isReady.value = true;
        resolve();
      },
      fail: (err) => {
        reject(err);
      },
    });
  });
};

const setData = async (id: any, gender: any, type: any) => {
  chartData.value = undefined;
  let oldChartData: any = {};
  const patientChartData: any = {
    categories: [],
    series: [
      {
        name: "身高",
        data: [],
      },
    ],
  };

  await getPatientMonthData({
    patientId: id,
    code: "height",
  })
    .then((res: any) => {
      if (res && res.records.length > 0) {
        res.records.forEach((item: any) => {
          // const day = Math.floor(item.relativeTime / DAYTIMES);
          patientChartData.categories.push(item.relativeTime);
          patientChartData.series[0].data.push(Number(item.value));
        });
      }
    })
    .catch(() => {
      patientChartData.categories = [];
      patientChartData.series[0].data = [];
    });

  if (type == "PValue") {
    if (gender == 1) {
      oldChartData = chartJson.value.PManHeightData;
    } else if (gender == 2) {
      oldChartData = chartJson.value.PWomanHeightData;
    } else {
      oldChartData = chartJson.value.PManHeightData;
    }
  } else if (type == "SDValue") {
    if (gender == 1) {
      oldChartData = chartJson.value.SDManData;
    } else if (gender == 2) {
      oldChartData = chartJson.value.SDWomanData;
    } else {
      oldChartData = chartJson.value.SDManData;
    }
  }

  const oldData = monthDayFormat(oldChartData.categories, oldChartData.series);

  // if (patientChartData && patientChartData.categories.length > 0) {
  chartData.value = await mergeChartData(
    oldData.categories,
    oldData.series,
    patientChartData.categories,
    patientChartData.series,
    type
  );
  // } else {
  //   chartData.value = JSON.parse(JSON.stringify(oldChartData));
  // }
  if (chartData.value?.categories.length) {
    opts.xAxis.itemCount = chartData.value.categories.length;
  }
  console.log(chartData.value);
};

// 患者身高数据整合
const mergeChartData = (
  oldCategories,
  oldSeries,
  newCategories,
  newSeries,
  type,
  fillValue = null
) => {
  const categorySet = new Set([...oldCategories]);

  for (const c of newCategories || []) {
    categorySet.add(c);
  }
  const finalCategories = Array.from(categorySet).sort(
    (a, b) => Number(a) - Number(b)
  );

  const categoryIndexMap: any = {};
  finalCategories.forEach((cat, i) => {
    categoryIndexMap[cat] = i;
  });

  const remappedOldSeries = oldSeries.map((series) => {
    const newData = new Array(finalCategories.length).fill(fillValue);

    oldCategories.forEach((cat, i) => {
      const idx = categoryIndexMap[cat];
      newData[idx] = series.data[i];
    });
    // console.log(newData, "newData");

    // console.log(interpolateNulls(newData));

    return {
      ...series,
      data: interpolateNulls(newData),
      connectNulls: true,
      style: "curve",
      type: "line",
    };
  });

  const remappedOldSeriesMix: any = [];
  if (type === "PValue") {
    const areaData = [3, 4];
    const lineData = [0, 1, 2];

    remappedOldSeriesMix.push({
      type: "area-range",
      style: "curve",
      color: "#E5FAF8",
      upperData: remappedOldSeries[4].data,
      lowerData: remappedOldSeries[2].data,
      disableLegend: true,
      showSymbol: false,
    });

    remappedOldSeries.forEach((series) => {
      remappedOldSeriesMix.push({
        ...series,
        type: "line",
        style: "curve",
      });
    });
  } else {
    const areaData = [2, 3, 4, 5];
    const lineData = [0, 1];
    remappedOldSeriesMix.push({
      type: "area-range",
      style: "curve",
      color: "#E5FAF8",
      upperData: remappedOldSeries[5].data,
      lowerData: remappedOldSeries[1].data,
      disableLegend: true,
      showSymbol: false,
    });

    remappedOldSeries.forEach((series) => {
      remappedOldSeriesMix.push({
        ...series,
        type: "line",
        style: "curve",
      });
    });
  }

  const remappedNewSeries = newSeries.map((series) => {
    const newData = new Array(finalCategories.length).fill(fillValue);
    newCategories.forEach((cat, i) => {
      const idx = categoryIndexMap[cat];
      newData[idx] = series.data[i];
    });

    return {
      ...series,
      data: newData,
      connectNulls: true,
      addPoint: true,
      style: "curve",
      type: "line",
    };
  });

  return {
    categories: finalCategories,
    series: [...remappedOldSeriesMix, ...remappedNewSeries],
  };
};

// 月刻度 数据转换为天刻度
const monthDayFormat = (oldCategories, oldSeries) => {
  const categories = oldCategories.map((vo) => {
    return vo * DAYSMONTH * DAYTIMES;
  });

  const series = oldSeries.map((vo) => {
    const newData = new Array(categories.length).fill(null);
    categories.forEach((cat, i) => {
      newData[i] = vo.data[i];
    });
    return {
      ...vo,
      data: newData,
      connectNulls: true,
    };
  });

  return {
    categories: categories,
    series: series,
  };
};

const interpolateNulls = (data) => {
  const result = [...data];
  let i = 0;
  while (i < result.length) {
    if (result[i] === null) {
      let start = i - 1;
      let end = i;
      while (end < result.length && result[end] === null) {
        end++;
      }
      if (start >= 0 && end < result.length) {
        const count = end - start;
        const step = (result[end] - result[start]) / count;
        for (let j = 1; j < count; j++) {
          const value = result[start] + step * j;
          result[start + j] = {
            value: Math.round(value * 100) / 100,
            show: false,
          };
        }
      }
      i = end;
    } else {
      i++;
    }
  }
  return result;
};

defineExpose({
  setData,
});
</script>
<style lang="scss" scoped></style>
